Industrial controllers are special purpose computers used for controlling industrial processes or manufacturing equipment.
Under the direction of a stored program, the industrial controller examines a series of inputs reflecting the status of a controlled process and changes outputs effecting control of the process. The inputs and outputs are most simply binary, that is "on" or "off"; however, analog inputs and outputs, taking on a continuous range of values, are also used.
Industrial controllers are frequently programmed in a "relay ladder" language where instructions are represented graphically by "contacts" and "coils" of virtual relays connected and arranged in ladder-like rungs. This relay ladder language, with its input contacts and output coils, reflects the emphasis in industrial control on the processing of large amounts of input and output data. The relay ladder language also reflects the fact that most industrial control is "real-time"; that is, an ideal industrial controller behaves as if it were actually composed of multiple relays connected in parallel rungs to provide outputs in essentially instantaneous response to changing inputs.
Other industrial control languages are also used including: function block languages which represent instructions as functional blocks having inputs and outputs connected to the inputs of other functional blocks; sequential function chart languages which represent the control process as a series of discrete states responsive to historical input and output data, and structured text languages which most closely resemble conventional computer programs such as FORTRAN and C.
Unlike programs written for industrial control, conventional computer programs frequently contain instructions causing loops in their execution pending an external event, for example, where the processor repeats a test instruction until an input condition is satisfied. Such loops can cause the execution time of the program to vary substantially, depending on how soon the external condition is satisfied.
In contrast, programs written for real-time control normally are fashioned to have a well defined execution time as they cycle through the program from beginning to end. This is a result, in part, of the need for these programs to process many inputs and outputs concurrently. If the processor "waits" for one input, e.g. by looping, this waiting adversely affects the speed of the processing of the other inputs.
For a control program written in ladder form, for example, the program continuously scans the "rungs" of the ladder reading inputs and writing outputs determined from those inputs and the logic of the ladder. The scanning time is relatively constant.
It would be desirable to write large programs for industrial controllers as separate "tasks" that could be independently run and checked. For example, different machines along a single assembly line might be controlled with separate programs, each written as a separate task. The tasks for different machines, although developed separately, could then run on a single processor in a manner so as to appear to be executing simultaneously. Apparent simultaneous execution would be obtained by rapidly switching a single processor between tasks. Controllers or computers having operating systems that permit the simultaneous execution of multiple tasks are termed "multi-tasking".
The tasks that are normally executed in a conventional computer environment are largely independent of one another. In contrast, the task executed in an industrial control environment are normally highly interrelated as a result of the physical linkage between the parts of the process they control. For example, in an industrial control situation, if one task is controlling the positioning of containers on a conveyor belt and another task is controlling the dispensing of ingredients into those containers, these tasks must communicate between each other to coordinate their actions logically and in time.
One method of coordinating multiple tasks is through the use of "global" memory which may be accessed by all tasks. Common variables and flags stored in global memory may be used to permit the tasks to communicate data and timing information. More generally, the tasks may use global memory to share instructions for common routines employed by more than one task.
The use of global memory that may be read and written to by a number of tasks can make it difficult to identify minor code errors or "bugs" relating to the execution of a given task. For controllers executing only a single task and executing instructions from re-writable memory, instructions ("breakpoints") may be inserted into the task being executed to stop the task at certain points in the task program so as to output values of certain memory locations to the operator. These breakpoint instructions allow the operator to observe the progress of the task program as it is reflected in the changes in memory values caused by the task program, and thus to evaluate the operation of the task on a step-by-step basis. Breakpoint instructions inserted into the program being executed are not possible when that program is firmware as may be contained in read-only-memory.
In a multi-tasking industrial control system, the multiple tasks may interrupt each other on an unpredictable basis and the multiple tasks are executed without predetermined order. Accordingly, the view of the operation of a first task provided by a breakpoint instruction in that task, may be immediately corrupted by a second task interrupting the first task. Generally, the fact that a given global memory address has a particular value at one point in a given task does not ensure that value of that memory location is the same when the next step of the task is executed. As a result, evaluating multi-tasking realtime operating systems, employing significant amounts of global memory, is difficult.